﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using Celeriq.Common;

namespace Celeriq.RepositoryAPI
{
	[Serializable]
	[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
	public class RepositoryService : Celeriq.Common.IDataModel, Celeriq.Utilities.IRepositoryService
	{
		private Celeriq.RepositoryAPI.Repository _repository = null;
		private Guid _repositoryId = Guid.Empty;
		private long _minMemory = 0;

		public RepositoryService()
		{
			_minMemory = System.Diagnostics.Process.GetCurrentProcess().WorkingSet64;
		}

		public DateTime LastAccess
		{
			get { return  _repository.LastAccess; }
		}

		public void UnloadData()
		{
			try
			{
				if (_repository != null)
					_repository.UnloadData();
			}
			catch (Exception ex)
			{
				Celeriq.Utilities.Logger.LogError(ex.ToString());
			}
		}

		public string[] UpdateData(IEnumerable<DataItem> list, UserCredentials credentials)
		{
			var errorList = new List<string>();
			try
			{
				if (_repository == null)
					errorList.Add("The repository has not been initialized!");
				else
					_repository.UpdateIndexList(list, credentials);
			}
			catch (Exception ex)
			{
				Celeriq.Utilities.Logger.LogError(ex.ToString());
				errorList.Add(ex.ToString());
			}
			return errorList.ToArray();
		}

		public string[] DeleteData(IEnumerable<DataItem> item, UserCredentials credentials)
		{
			var errorList = new List<string>();
			try
			{
				if (_repository == null)
					errorList.Add("The repository has not been initialized!");
				else
					_repository.DeleteData(item, credentials);
			}
			catch (Exception ex)
			{
				Celeriq.Utilities.Logger.LogError(ex.ToString());
				errorList.Add(ex.ToString());
			}
			return errorList.ToArray();
		}

		public string[] Clear(UserCredentials credentials)
		{
			var errorList = new List<string>();
			try
			{
				if (_repository == null)
				{
					errorList.Add("The repository has not been initialized!");
				}
				else
				{
					_repository.Clear(credentials);
				}
			}
			catch (Exception ex)
			{
				Celeriq.Utilities.Logger.LogError(ex.ToString());
				errorList.Add(ex.ToString());
			}
			return errorList.ToArray();
		}

		public DataQueryResults Query(DataQuery query)
		{
			var retval = new DataQueryResults();
			try
			{
				if (_repository == null)
				{
					retval.ErrorList = new string[] {"The repository has not been initialized!"};
				}
				else
				{
					retval = _repository.Query(query);
				}
			}
			catch (Exception ex)
			{
				Celeriq.Utilities.Logger.LogError(ex.ToString());
				retval.ErrorList = new string[] {ex.ToString()};
			}
			return retval;
		}

		public int StartUp(Celeriq.Utilities.ServiceStartup startup)
		{
			if (_repository != null)
				throw new Exception("The repository has already been initialized!");

			if (startup == null)
				throw new Exception("The startup object must be specified!");

			if (startup.RepositoryDefinition == null)
				throw new Exception("The repository definition must be specified!");

			if (string.IsNullOrEmpty(startup.RepositoryFolder))
				throw new Exception("The repository folder must be specified!");

			try
			{
				_repositoryId = startup.RepositoryDefinition.ID;
				_repository = new Celeriq.RepositoryAPI.Repository(startup);
				//var results = _repository.Query(new DataQuery());
				//return results.TotalRecordCount;
				return (int)_repository.GetItemCount();
			}
			catch (Exception ex)
			{
				Celeriq.Utilities.Logger.LogError(ex.ToString());
				return 0;
			}
		}

		public void ShutDown()
		{
			if (_repository == null)
				throw new Exception("The repository has not been initialized!");

			_repository = null;
		}

		/// <summary>
		/// Clears all data from the repository
		/// </summary>
		/// <param name="startup"></param>
		public void Reset(Celeriq.Utilities.ServiceStartup startup)
		{
			try
			{
				if (_repository == null) StartUp(startup);
				_repository.Reset(startup);
			}
			catch (Exception ex)
			{
				Celeriq.Utilities.Logger.LogError(ex.ToString());
				throw;
			}
		}

		public Guid GetID()
		{
			return _repositoryId;
		}

		/// <summary>
		/// Copies the entire repository to an archive file
		/// </summary>
		public bool ExportSchema(Celeriq.Utilities.ServiceStartup startup, UserCredentials credentials, string backupFile)
		{
			try
			{
				if (_repository == null) StartUp(startup);
				return _repository.ExportSchema(startup, credentials, backupFile);
			}
			catch (Exception ex)
			{
				Celeriq.Utilities.Logger.LogError(ex.ToString());
				throw;
			}
		}

		/// <summary>
		/// Copies the entire repository to an archive file
		/// </summary>
		public bool Backup(Celeriq.Utilities.ServiceStartup startup, UserCredentials credentials, string backupFile)
		{
			try
			{
				if (_repository == null) StartUp(startup);
				return _repository.Backup(startup, credentials, backupFile);
			}
			catch (Exception ex)
			{
				Celeriq.Utilities.Logger.LogError(ex.ToString());
				throw;
			}
		}

		public bool Restore(Celeriq.Utilities.ServiceStartup startup, UserCredentials credentials, string backupFile)
		{
			try
			{
				if (_repository == null) StartUp(startup);
				return _repository.Restore(startup, credentials, backupFile);
			}
			catch (Exception ex)
			{
				Celeriq.Utilities.Logger.LogError(ex.ToString());
				throw;
			}
		}

		/// <summary>
		/// Returns the size on disk of the repository data
		/// </summary>
		/// <returns></returns>
		public long? GetDataSize(UserCredentials credentials)
		{
			try
			{
				if (_repository == null) return null;
				return _repository.GetDataSize(credentials);
			}
			catch (Exception ex)
			{
				Celeriq.Utilities.Logger.LogError(ex.ToString());
				throw;
			}
		}

		/// <summary>
		/// Returns the number of items in the repository
		/// </summary>
		/// <returns></returns>
		public long? GetItemCount(UserCredentials credentials)
		{
			try
			{
				if (_repository == null) return null;
				return _repository.GetItemCount(credentials);
			}
			catch (Exception ex)
			{
				Celeriq.Utilities.Logger.LogError(ex.ToString());
				throw;
			}
		}

		public void Compress(UserCredentials credentials)
		{
			try
			{
				if (_repository == null)
					throw new Exception("The repository has not been initialized!");
				
				_repository.Compress(credentials);
			}
			catch (Exception ex)
			{
				Celeriq.Utilities.Logger.LogError(ex.ToString());
				throw;
			}
		}

	}
}